package io.renren.modules.media.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;

import cn.hutool.core.collection.CollectionUtil;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.common.utils.UuidUtils;
import io.renren.modules.media.dao.MediaJobInfoDao;
import io.renren.modules.media.entity.MediaInfoEntity;
import io.renren.modules.media.entity.MediaJobCapturePictureEntity;
import io.renren.modules.media.entity.MediaJobInfoEntity;
import io.renren.modules.media.entity.MediaJobMontageEntity;
import io.renren.modules.media.entity.MediaJobRecordEntity;
import io.renren.modules.media.enums.JobStatus;
import io.renren.modules.media.enums.MediaJobType;
import io.renren.modules.media.ffmpeg.MediaProcessing;
import io.renren.modules.media.ffmpeg.RecordMedia;
import io.renren.modules.media.model.ImageInfo;
import io.renren.modules.media.model.MediaCapturePictureJobReq;
import io.renren.modules.media.model.MediaCutJobReq;
import io.renren.modules.media.model.MediaRecordJobReq;
import io.renren.modules.media.model.MediaSplicingJobReq;
import io.renren.modules.media.service.MediaInfoService;
import io.renren.modules.media.service.MediaJobCapturePictureService;
import io.renren.modules.media.service.MediaJobInfoService;
import io.renren.modules.media.service.MediaJobMontageService;
import io.renren.modules.media.service.MediaJobRecordService;
import io.renren.modules.media.service.PictureInfoService;
import io.renren.modules.media.support.MinioSupport;
import lombok.extern.log4j.Log4j2;


@Log4j2
@Service("mediaJobInfoService")
public class MediaJobInfoServiceImpl extends ServiceImpl<MediaJobInfoDao, MediaJobInfoEntity> implements MediaJobInfoService {

	private static String videoPath = "video/";
	
	private static String picturePath = "picture/";
	
	@Autowired
    private MediaJobRecordService mediaJobRecordService;
    
    @Autowired
    private MediaInfoService mediaInfoService;
    
    @Autowired
    private MinioSupport minioSupport;
    
    @Autowired
    private MediaJobMontageService mediaJobMontageService;
    
    @Autowired
    private PictureInfoService pictureInfoService;
    
    @Autowired
    private MediaJobCapturePictureService mediaJobCapturePictureService;
   
	
	@Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MediaJobInfoEntity> page = this.page(
                new Query<MediaJobInfoEntity>().getPage(params),
                new QueryWrapper<MediaJobInfoEntity>()
        );

        return new PageUtils(page);
    }


	@Override
	public void recordJob(MediaRecordJobReq req) {
		MediaJobInfoEntity info = new MediaJobInfoEntity();
		String jobId = UuidUtils.getUUID32();
		info.setJobId(jobId);
		info.setStatus(JobStatus.START.getCode());
		info.setType(MediaJobType.RECORD.getCode());
		info.setDetail(JSON.toJSONString(req));
		info.setCreateTime(new Date());
		save(info);

		String filePath;
		int fileId = 0;
		try {
			filePath = RecordMedia.record(req.getUrl(), req.getDuration());
			File file = new File(filePath);
			// 上传文件
			minioSupport.uploadFile(new FileInputStream(file), "media", videoPath+ file.getName(), null);
			// 保存文件信息
			fileId = mediaInfoService.saveInfo(jobId,file.getName(), videoPath ,req.getType(), file);
		} catch (java.lang.Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		MediaJobRecordEntity recordInfo = new MediaJobRecordEntity();
		recordInfo.setJobId(jobId);
		recordInfo.setType(req.getType());
		recordInfo.setDuration(req.getDuration());
		recordInfo.setUrl(req.getUrl());
		recordInfo.setCreateTime(new Date());
		recordInfo.setFileId(fileId);
		mediaJobRecordService.save(recordInfo);
		
		MediaJobInfoEntity updateInfo = new MediaJobInfoEntity();
		updateInfo.setId(info.getId());
		updateInfo.setStatus(JobStatus.SUCCESS.getCode());
		updateInfo.setUpdateTime(new Date());
		updateById(updateInfo);
	}


	@Override
	public boolean cutJob(MediaCutJobReq req) {
		MediaJobInfoEntity info = new MediaJobInfoEntity();
		
		String detail =  JSON.toJSONString(req);
		
		String jobId = UuidUtils.getUUID32();
		info.setJobId(jobId);
		info.setStatus(JobStatus.START.getCode());
		info.setType(MediaJobType.CUT.getCode());
		info.setDetail(detail);
		info.setCreateTime(new Date());
		save(info);
		
		MediaJobInfoEntity updateInfo = new MediaJobInfoEntity();
		updateInfo.setId(info.getId());
		
		MediaInfoEntity mediaInfo = mediaInfoService.getById(req.getFileId());
		if(null == mediaInfo) {
			updateInfo.setStatus(JobStatus.FAIL.getCode());
			updateInfo.setUpdateTime(new Date());
			updateInfo.setDetail(detail+"::error:源文件不存在");
			updateById(updateInfo);
			return false;
		}
		String fileUrl = minioSupport.previewAddress("media", mediaInfo.getFilePath()+mediaInfo.getFileName(), 300);
		
		String filePath = MediaProcessing.cutVideo(fileUrl, req.getStartTime(), req.getEndTime());
		if(StringUtils.isBlank(filePath)) {
			updateInfo.setStatus(JobStatus.FAIL.getCode());
			updateInfo.setUpdateTime(new Date());
			updateInfo.setDetail(detail+"::error:视频截取失败");
			updateById(updateInfo);
			return false;
		}
		
		File file = new File(filePath);
		// 上传文件
		try {
			minioSupport.uploadFile(new FileInputStream(file), "media", videoPath+ file.getName(), null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 保存文件信息
		int cutAfterId = mediaInfoService.saveInfo(jobId,file.getName(), videoPath,req.getType(), file);
		
		MediaJobMontageEntity cutInfo = new MediaJobMontageEntity();
		cutInfo.setJobId(jobId);
		cutInfo.setType(1);
		cutInfo.setMediaType(req.getType());
		cutInfo.setCutStartTime(req.getStartTime());
		cutInfo.setCutEndTime(req.getEndTime());
		cutInfo.setCutBeforeId(req.getFileId());
		cutInfo.setCutAfterId(cutAfterId);
		cutInfo.setCreateTime(new Date());
		mediaJobMontageService.save(cutInfo);
		
		updateInfo.setStatus(JobStatus.SUCCESS.getCode());
		updateInfo.setUpdateTime(new Date());
		updateById(updateInfo);
		return true;
	}


	@Override
	public boolean splicingJob(MediaSplicingJobReq req) {
		MediaJobInfoEntity info = new MediaJobInfoEntity();
		
		String detail =  JSON.toJSONString(req);
		
		String jobId = UuidUtils.getUUID32();
		info.setJobId(jobId);
		info.setStatus(JobStatus.START.getCode());
		info.setType(MediaJobType.SPLICING.getCode());
		info.setDetail(detail);
		info.setCreateTime(new Date());
		save(info);
		
		MediaJobInfoEntity updateInfo = new MediaJobInfoEntity();
		updateInfo.setId(info.getId());
		
		MediaInfoEntity mediaInfoOne = mediaInfoService.getById(req.getFileOne());
		if(null == mediaInfoOne) {
			updateInfo.setStatus(JobStatus.FAIL.getCode());
			updateInfo.setUpdateTime(new Date());
			updateInfo.setDetail(detail+"::error:源文件一不存在");
			updateById(updateInfo);
			return false;
		}
		
		MediaInfoEntity mediaInfoTwo = mediaInfoService.getById(req.getFileTwo());
		if(null == mediaInfoTwo) {
			updateInfo.setStatus(JobStatus.FAIL.getCode());
			updateInfo.setUpdateTime(new Date());
			updateInfo.setDetail(detail+"::error:源文件二不存在");
			updateById(updateInfo);
			return false;
		}
		
		String fileOneUrl = minioSupport.previewAddress("media", mediaInfoOne.getFilePath()+mediaInfoOne.getFileName(), 300);
		String fileTwoUrl = minioSupport.previewAddress("media", mediaInfoOne.getFilePath()+mediaInfoTwo.getFileName(), 300);
		
		ArrayList<String> urlList = Lists.newArrayList();
		urlList.add(fileOneUrl);
		urlList.add(fileTwoUrl);
		
		
		String filePath = MediaProcessing.splicing(urlList);
		if(StringUtils.isBlank(filePath)) {
			updateInfo.setStatus(JobStatus.FAIL.getCode());
			updateInfo.setUpdateTime(new Date());
			updateInfo.setDetail(detail+"::error:视频拼接失败");
			updateById(updateInfo);
			return false;
		}
		
		File file = new File(filePath);
		// 上传文件
		try {
			minioSupport.uploadFile(new FileInputStream(file), "media", videoPath+ file.getName(), null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 保存文件信息
		int mergeAfterId = mediaInfoService.saveInfo(jobId,file.getName(), videoPath,req.getType(), file);
		
		MediaJobMontageEntity splicingInfo = new MediaJobMontageEntity();
		splicingInfo.setJobId(jobId);
		splicingInfo.setType(2);
		splicingInfo.setMediaType(req.getType());
		splicingInfo.setMergeBeforeIds(req.getFileOne()+","+req.getFileTwo());
		splicingInfo.setMergeAfterId(mergeAfterId);
		splicingInfo.setCreateTime(new Date());
		mediaJobMontageService.save(splicingInfo);
		
		updateInfo.setStatus(JobStatus.SUCCESS.getCode());
		updateInfo.setUpdateTime(new Date());
		updateById(updateInfo);
		return true;
	}


	@Override
	public boolean capturePictureJob(MediaCapturePictureJobReq req) {
		MediaJobInfoEntity info = new MediaJobInfoEntity();
		
		String detail =  JSON.toJSONString(req);
		
		String jobId = UuidUtils.getUUID32();
		info.setJobId(jobId);
		info.setStatus(JobStatus.START.getCode());
		info.setType(MediaJobType.CAPTURE.getCode());
		info.setDetail(detail);
		info.setCreateTime(new Date());
		save(info);
		
		MediaJobInfoEntity updateInfo = new MediaJobInfoEntity();
		updateInfo.setId(info.getId());
		
		MediaInfoEntity mediaInfo = mediaInfoService.getById(req.getFileId());
		if(null == mediaInfo) {
			updateInfo.setStatus(JobStatus.FAIL.getCode());
			updateInfo.setUpdateTime(new Date());
			updateInfo.setDetail(detail+"::error:源文件不存在");
			updateById(updateInfo);
			return false;
		}
		String fileUrl = minioSupport.previewAddress("media", mediaInfo.getFilePath()+mediaInfo.getFileName(), 300);
		List<ImageInfo> imageList = MediaProcessing.capture(fileUrl, req.getTime(), req.getSum(), req.getImageFormat());
		
		
		String ids = "";
		if(CollectionUtil.isNotEmpty(imageList)) {
			for(ImageInfo imageInfo : imageList) {
				File file = new File(imageInfo.getPath());
				// 上传文件
				try {
					minioSupport.uploadFile(new FileInputStream(file), "media", picturePath+ file.getName(), null);
				} catch (Exception e) {
					e.printStackTrace();
				}
				int pictureId = pictureInfoService.saveInfo(jobId, imageInfo.getName(), picturePath, req.getImageFormat(), imageInfo.getWidth(), imageInfo.getHeight());
				ids=ids+pictureId+",";
			}
		}else{
			log.info("未截取到图片：{}",JSON.toJSONString(req));
		}
		
		if(StringUtils.isNotBlank(ids)) {
			ids = ids.substring(0, ids.length() - 1);
		}
		
		MediaJobCapturePictureEntity entity = new MediaJobCapturePictureEntity();
		entity.setJobId(jobId);
		entity.setTime(req.getTime());
		entity.setFileId(req.getFileId());
		entity.setSum(req.getSum());
		entity.setFileFormat(req.getImageFormat());
		entity.setIds(ids);
		entity.setCreateTime(new Date());
		mediaJobCapturePictureService.save(entity);
		
		updateInfo.setStatus(JobStatus.SUCCESS.getCode());
		updateInfo.setUpdateTime(new Date());
		updateById(updateInfo);
		return true;
	}

}